
/*************************************************************************
** File		: AppRecver.h
** Desc     : 广播接收器，应用场不同于MsgQue。
**				AppRecver应用于向整个应用范围内通知消息；
**				MsgQue应用于应用范围内向某个处理中心发消息或数据；
**			 原先的设计理念：广播接收器与普通监听器的区别在于，
**				前者处理全app范围内的公共消息，故全app只有一个广播接收器，不需要被观察者显式调用注册/反注册接口
**				后者处理被观察者的消息，监听器与被观察者通常一对一或一对多，需要被观察者显式调用注册/反注册接口
** Author   : xktesla@2017-5-23 08:39:02
*************************************************************************/


#ifndef _FCD11799_0EF8_422F_AD8E_AF49CD87781D
#define _FCD11799_0EF8_422F_AD8E_AF49CD87781D

#include "depends/incfile.h"
#include "xCores.h"


namespace x2lib
{

class AppRecver
{
public:
	enum
	{
		ACT_BASE = 0x2000,
		ACT_END = 0x3000, // 作为RegistAction可变参的结尾标记
	};

	virtual void OnAppAction(int iPi, int iArg0, void *vArg1, char sArg2[1024]) = 0;

	static bool Initialize()
	{
		return AppEngine::GetInstance()->Start();
	}

	static void UnInitialize()
	{
		AppEngine::GetInstance()->Stop();
	}

	/*************************************************************************
	** Desc		: 注册Action
	** Param	: [in] nLvl 欲插入的位置，0表示在最前面，(-1)表示插入到末尾
	** Param	: [in] ... 要注册的Action，必须以AppRecver::ACT_NULL作为变参最后一项；
	** Return	: 
	** Author	: xktesla@2018-2-9 17:29:22
	*************************************************************************/
	void RegistAction(int nLvl, ...)
	{
		va_list body;
		va_start(body, nLvl);
		AppEngine::GetInstance()->RegistAction(this, nLvl, body);
		va_end(body);
	}

	/*************************************************************************
	** Desc		: 注册Action
	** Param	: [in] nAct0 为ACT_NULL时，表示反注册所有Action
	** Param	: [in] ... 欲反注册的Action，必须以AppRecver::ACT_NULL作为变参最后一项，当第1项为AppRecver::ACT_NULL时表示反注册所有Action
	** Return	:
	** Author	: xktesla@2018-2-9 17:29:22
	*************************************************************************/
	void UnRegistAction(int nAct0=ACT_END, ...)
	{
		va_list body;
		va_start(body, nAct0);
		AppEngine::GetInstance()->UnRegistAction(this, nAct0, body);
		va_end(body);
	}

	// SendPill
	static bool SendAction(int iArg0, int iArg1, void *vArg2, char sArg3[1024])
	{
		return AppEngine::GetInstance()->SendAction(iArg0, iArg1, vArg2, sArg3);
	}

	static void PostAction(int iArg0, int iArg1, void *vArg2, char sArg3[1024])
	{
		AppEngine::GetInstance()->PostAction(iArg0, iArg1, vArg2, sArg3);
	}

private:

	class AppEngine :public xCores::Engine
	{
	private:
		AppEngine()
		{
			m_pSignal = new xCores::Signal(0);
		};
		virtual ~AppEngine()
		{ 
			delete m_pSignal;
		};
	public:
		static AppEngine* GetInstance()
		{
			static AppEngine *pAppEngine = nullptr;
			if (!pAppEngine) pAppEngine = new AppEngine();
			return pAppEngine;
		}

		bool Start()
		{
			return (0<(ID_CYLONLY = Ignite(nullptr)));
		}

		void Stop()
		{
			Stall(ID_CYLONLY, 1000);
		}

		// 由Ignite触发
		virtual void onEngineExec(uint32_t id, void* vData) override
		{
			m_msgQue.Loop(&AppEngine::AppSender, this);
		}
		// 由Stall触发
		virtual void onEngineExit(uint32_t id, void* vData) override {}

		bool AppSender(int iArg0, int iArg1, void *vArg2, char sArg3[1024])
		{
			for (std::map<AppRecver*, std::vector<int> >::iterator it = m_mapReceiver.begin(); it != m_mapReceiver.end(); it++)
			{
				std::vector<int>::iterator itFind = std::find(it->second.begin(), it->second.end(), iArg0);//it->second.begin();
				if (itFind != it->second.end())
				{
					it->first->OnAppAction(iArg0, iArg1, vArg2, sArg3);
				}
			}
			m_pSignal->Acquire(1);

			return true;
		}

	protected:
		// 0参表示注册所有
		void RegistAction(AppRecver *pReceiver, int nLvl, va_list body)
		{
			std::vector<int> vecAct;
			int nAct = va_arg(body, int);
			for (int i = nAct; i < ACT_END; i = va_arg(body, int))
			{
				//vecAct.insert(nLvl, i);
				// xktesla@2019-8-28 10:27:24 临时修改为了VC_LTL编译通过，逻辑可能是错误的
				vecAct.insert(vecAct.begin(), i);
			}
			m_mapReceiver[pReceiver] = vecAct;
		}
		// 0参表示反注册所有
		void UnRegistAction(AppRecver *pReceiver, int nAct0, va_list body)
		{
			//LOG_PRINT_D("nAct=%08X,pReceiver=%d,m_mapReceiver[pReceiver].size()=%d\n", nAct, pReceiver, m_mapReceiver[pReceiver].size());
			if (nAct0 == ACT_END)
			{
				m_mapReceiver[pReceiver].clear();
			}
			else
			{
				for (int i = va_arg(body, int); i < ACT_END; i = va_arg(body, int))
				{
					std::vector<int>::iterator it = std::find(m_mapReceiver[pReceiver].begin(), m_mapReceiver[pReceiver].end(), i);
					if (it != m_mapReceiver[pReceiver].end())
						m_mapReceiver[pReceiver].erase(it);
				}
			}
		}

		bool SendAction(int iPi, int iArg0, void *vArg1, char sArg2[1024])
		{
			PostAction(iPi, iArg0, vArg1, sArg2);
			m_pSignal->Acquire();
			return true;
		}

		void PostAction(int iPi, int iArg0, void *vArg1, char sArg2[1024])
		{
			m_msgQue.Post(iPi, iArg0, vArg1, sArg2);
		}

	private:
		int ID_CYLONLY;
		xCores::Signal *m_pSignal;
		std::map<AppRecver*, std::vector<int> > m_mapReceiver;
		xCores::MsgQue<AppEngine> m_msgQue;
		friend class AppRecver;
	};
};

}


// 用例
// AppRecver::SendAction(AppRecver::AP_ONSEND, this, DatX);
// AppRecver::PostAction(AppRecver::AP_ONSEND, this, DatX);
//public interface AppListener {
//	public void onAppReceive(String action, Intent intent);
//}

#endif

